package http_server

import (
	"easy_http/http_validation"
	"encoding/json"
	"errors"
	"io"
	"net/http"
)

type Context struct {
	W        http.ResponseWriter
	R        *http.Request
	Params   map[string]string
	handlers []HandlerFunc
	index    int // 记录当前执行到第几个中间件
	engine   *Engine
}

//type HandlerFunc func(*Context)

// HandlersChain 定义HandlerFunc切片
type HandlersChain []HandlerFunc

func (ctx *Context) SetHandler() {

}

// ReadJson 请求体响应
func (ctx *Context) ReadJson(obj interface{}) error {
	// 读取Body，并且序列化
	r := ctx.R
	all, err := io.ReadAll(r.Body)
	if err != nil {
		return err
	}
	err = json.Unmarshal(all, &obj)
	if err != nil {
		return err
	}

	return nil
}

// WriteJson 返回体响应
func (ctx *Context) WriteJson(code int, resp interface{}) error {
	ctx.SetHeader("Content-Type", "application/json")
	ctx.W.WriteHeader(code)
	respJson, err := json.Marshal(resp)
	if err != nil {
		return err
	}
	_, err = ctx.W.Write(respJson)
	return err
}

// OKJson 响应成功
func (ctx *Context) OKJson(resp interface{}) error {
	return ctx.WriteJson(http.StatusOK, resp)
}

// NewContext 对Context创建的实现
func NewContext(w http.ResponseWriter, r *http.Request) *Context {
	/* 对外暴露该接口，隐藏Context实现的细节，用户只需要在需要的地方调用NewContext()接口即可*/
	return &Context{
		W:     w,
		R:     r,
		index: -1,
	}
}

// ShouldBindJson 解析Json字符串，并校验
func (ctx *Context) ShouldBindJson(obj any) error {
	// 对数据必传参数进行校验
	if obj == nil || ctx.R.Body == nil {
		return errors.New("请求参数无效")
	}

	err := json.NewDecoder(ctx.R.Body).Decode(obj)
	if err != nil {
		return err
	}
	// 校验数据
	err = http_validation.Validation(obj)
	if err != nil {
		return err
	}
	return nil

}

// Next 只在中间件内部使用
func (ctx *Context) Next() {
	ctx.index++ // 当前执行中间件
	s := len(ctx.handlers)
	for ; ctx.index < s; ctx.index++ {
		ctx.handlers[ctx.index](ctx)
	}
}

// PostForm 获取表单数据
func (ctx *Context) PostForm(key string) string {
	return ctx.R.FormValue(key)
}

// Query 查询参数，如果不存在返回空字符串""
func (ctx *Context) Query(key string) string {
	return ctx.R.URL.Query().Get(key)
}

// QueryDefault 查询参数，如果不存在返回默认值，这里默认返回"Default"
func (ctx *Context) QueryDefault(key string) string {
	query := ctx.R.URL.Query().Get(key)
	if query == "" {
		return "Default"
	}
	return query
}

// SetHeader 设置响应头信息
func (ctx *Context) SetHeader(key, value string) {
	ctx.W.Header().Set(key, value)
}

// GetHeader 获取响应头信息
func (ctx *Context) GetHeader(key string) string {
	return ctx.R.Header.Get(key)
}

func (ctx *Context) Param(key string) string {
	value, _ := ctx.Params[key]
	return value

}

func (ctx *Context) HTML(code int, name string, data interface{}) {
	ctx.W.Header().Set("Content-Type", "text/html; charset=utf-8")
	ctx.W.WriteHeader(code)
	if err := ctx.engine.htmlTemplates.ExecuteTemplate(ctx.W, name, data); err != nil {
		ctx.W.WriteHeader(http.StatusInternalServerError)
		ctx.W.Write([]byte("500 internal server error"))
	}
}

/*
Cookie
Session
*/
